using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using NLog;

namespace LDNS.Monitor
{
    /// <summary>
    /// Windows DNS设置管理器
    /// 负责设置和管理Windows网络适配器的DNS服务器配置
    /// 作者：huobing
    /// </summary>
    public static class WindowsDnsManager
    {
        private static readonly Logger _logger = LogManager.GetCurrentClassLogger();
        private const string LOCALHOST_IP = "127.0.0.1";

        /// <summary>
        /// 设置本地主机(127.0.0.1)为首位DNS服务器
        /// </summary>
        /// <returns>是否设置成功</returns>
        public static bool SetLocalhostAsPrimaryDns()
        {
            try
            {
                _logger.Info("开始设置127.0.0.1为首位DNS服务器");
                
                // 获取所有网络适配器信息
                var adapters = GetNetworkAdapters();
                if (adapters.Count == 0)
                {
                    _logger.Warn("未找到活动的网络适配器");
                    return false;
                }
                
                bool anySuccess = false;
                foreach (var adapter in adapters)
                {
                    // 获取当前DNS设置
                    List<string> currentDns = GetCurrentDnsServers(adapter.InterfaceIndex);
                    
                    // 构建新的DNS服务器列表（127.0.0.1 + 现有DNS）
                    List<string> newDns = new List<string> { LOCALHOST_IP };
                    // 添加现有DNS服务器，但排除127.0.0.1
                    newDns.AddRange(currentDns.Where(ip => ip != LOCALHOST_IP));
                    
                    // 设置DNS服务器
                    if (SetDnsServers(adapter.InterfaceIndex, newDns))
                    {
                        _logger.Info($"成功设置适配器 '{adapter.Name}' 的DNS服务器: {string.Join(", ", newDns)}");
                        anySuccess = true;
                    }
                    else
                    {
                        _logger.Warn($"设置适配器 '{adapter.Name}' 的DNS服务器失败");
                    }
                }
                
                return anySuccess;
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "设置127.0.0.1为DNS服务器时发生异常");
                return false;
            }
        }

        /// <summary>
        /// 从DNS服务器列表中删除127.0.0.1
        /// </summary>
        /// <returns>是否删除成功</returns>
        public static bool RemoveLocalhostFromDns()
        {
            try
            {
                _logger.Info("开始从DNS服务器列表中删除127.0.0.1");
                
                // 获取所有网络适配器信息
                var adapters = GetNetworkAdapters();
                if (adapters.Count == 0)
                {
                    _logger.Warn("未找到活动的网络适配器");
                    return false;
                }
                
                bool anySuccess = false;
                foreach (var adapter in adapters)
                {
                    // 获取当前DNS设置
                    List<string> currentDns = GetCurrentDnsServers(adapter.InterfaceIndex);
                    
                    // 检查是否包含127.0.0.1
                    if (currentDns.Contains(LOCALHOST_IP))
                    {
                        // 过滤掉127.0.0.1的DNS服务器列表
                        List<string> newDns = currentDns.Where(ip => ip != LOCALHOST_IP).ToList();
                        
                        if (newDns.Count > 0)
                        {
                            // 如果还有其他DNS服务器，则设置这些服务器
                            if (SetDnsServers(adapter.InterfaceIndex, newDns))
                            {
                                _logger.Info($"成功从适配器 '{adapter.Name}' 删除127.0.0.1，保留DNS服务器: {string.Join(", ", newDns)}");
                                anySuccess = true;
                            }
                        }
                        else
                        {
                            // 如果没有其他DNS服务器，则设置为自动获取
                            if (SetDnsToAutomatic(adapter.InterfaceIndex))
                            {
                                _logger.Info($"成功从适配器 '{adapter.Name}' 删除127.0.0.1，并设置为自动获取DNS");
                                anySuccess = true;
                            }
                        }
                    }
                    else
                    {
                        _logger.Info($"适配器 '{adapter.Name}' 中未找到127.0.0.1 DNS服务器");
                    }
                }
                
                return anySuccess;
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "从DNS服务器列表中删除127.0.0.1时发生异常");
                return false;
            }
        }

        /// <summary>
        /// 检查系统中是否设置了127.0.0.1作为DNS服务器
        /// </summary>
        /// <returns>是否包含127.0.0.1</returns>
        public static bool HasLocalhostDns()
        {
            try
            {
                var adapters = GetNetworkAdapters();
                foreach (var adapter in adapters)
                {
                    var dnsServers = GetCurrentDnsServers(adapter.InterfaceIndex);
                    if (dnsServers.Contains(LOCALHOST_IP))
                    {
                        _logger.Info($"在适配器 '{adapter.Name}' 中检测到127.0.0.1 DNS服务器");
                        return true;
                    }
                }
                return false;
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "检查DNS服务器配置时发生异常");
                return false;
            }
        }

        /// <summary>
        /// 确保本地DNS服务器(127.0.0.1)作为首位DNS服务器
        /// 这个方法会在网络状态变化时被调用，确保本地DNS服务始终优先
        /// </summary>
        /// <returns>操作是否成功</returns>
        public static bool EnsureLocalhostPrimaryDns()
        {
            try
            {
                _logger.Info("检查并确保127.0.0.1作为首位DNS服务器");
                
                // 获取所有活跃的网络适配器
                var adapters = GetNetworkAdapters();
                if (adapters.Count == 0)
                {
                    _logger.Warn("未找到活动的网络适配器");
                    return false;
                }

                bool needsUpdate = false;
                
                // 检查每个适配器的DNS设置
                foreach (var adapter in adapters)
                {
                    var dnsServers = GetCurrentDnsServers(adapter.InterfaceIndex);
                    if (dnsServers.Count == 0 || 
                        !dnsServers[0].Equals(LOCALHOST_IP, StringComparison.OrdinalIgnoreCase))
                    {
                        needsUpdate = true;
                        _logger.Info($"网络适配器 '{adapter.Name}' 的首位DNS不是127.0.0.1，需要更新");
                        break;
                    }
                }
                
                // 如果需要更新，则设置127.0.0.1为首位DNS
                if (needsUpdate)
                {
                    _logger.Info("发现网络适配器的DNS设置需要更新，正在设置127.0.0.1为首位DNS服务器");
                    return SetLocalhostAsPrimaryDns();
                }
                else
                {
                    _logger.Debug("所有网络适配器的DNS设置已正确，无需更新");
                    return true;
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "确保本地DNS优先时发生错误");
                return false;
            }
        }

        /// <summary>
        /// 获取活动的网络适配器列表
        /// </summary>
        /// <returns>网络适配器信息列表</returns>
        private static List<AdapterInfo> GetNetworkAdapters()
        {
            List<AdapterInfo> adapters = new List<AdapterInfo>();
            
            try
            {
                // 使用netsh命令获取网络适配器信息
                Process process = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "netsh.exe",
                        Arguments = "interface ipv4 show interfaces",
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        CreateNoWindow = true
                    }
                };
                
                process.Start();
                string output = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
                
                // 解析输出，获取活动的网络适配器
                Regex regex = new Regex(@"\s+(\d+)\s+\d+\s+\d+\s+\d+\s+Enabled\s+(\S+.*?)$", RegexOptions.Multiline);
                MatchCollection matches = regex.Matches(output);
                
                foreach (Match match in matches)
                {
                    if (int.TryParse(match.Groups[1].Value, out int interfaceIndex))
                    {
                        string name = match.Groups[2].Value.Trim();
                        adapters.Add(new AdapterInfo { InterfaceIndex = interfaceIndex, Name = name });
                        _logger.Debug($"找到活动网络适配器: {name} (索引: {interfaceIndex})");
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "获取网络适配器信息失败");
            }
            
            return adapters;
        }

        /// <summary>
        /// 获取指定网络适配器的当前DNS服务器设置
        /// </summary>
        /// <param name="interfaceIndex">网络适配器索引</param>
        /// <returns>DNS服务器IP地址列表</returns>
        private static List<string> GetCurrentDnsServers(int interfaceIndex)
        {
            List<string> dnsServers = new List<string>();
            
            try
            {
                Process process = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "netsh.exe",
                        Arguments = $"interface ipv4 show dns name=\"{interfaceIndex}\"",
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        CreateNoWindow = true
                    }
                };
                
                process.Start();
                string output = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
                
                // 检查是否为自动获取
                if (output.Contains("自动配置") || !output.Contains("DNS服务器"))
                {
                    return dnsServers;
                }
                
                // 解析DNS服务器地址
                Regex regex = new Regex(@"DNS服务器\s*:\s*(\S+)", RegexOptions.Multiline);
                MatchCollection matches = regex.Matches(output);
                
                foreach (Match match in matches)
                {
                    string dns = match.Groups[1].Value.Trim();
                    dnsServers.Add(dns);
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"获取网络适配器索引 {interfaceIndex} 的DNS服务器信息失败");
            }
            
            return dnsServers;
        }

        /// <summary>
        /// 设置网络适配器的DNS服务器
        /// </summary>
        /// <param name="interfaceIndex">网络适配器索引</param>
        /// <param name="dnsServers">DNS服务器IP地址列表</param>
        /// <returns>是否设置成功</returns>
        private static bool SetDnsServers(int interfaceIndex, List<string> dnsServers)
        {
            if (dnsServers.Count == 0)
            {
                return false;
            }
            
            try
            {
                // 构建命令参数
                string dnsArgs = string.Join(" ", dnsServers.Select(dns => $"static {dns}"));
                string arguments = $"interface ipv4 set dns name=\"{interfaceIndex}\" {dnsArgs}";
                
                Process process = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "netsh.exe",
                        Arguments = arguments,
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        CreateNoWindow = true,
                        Verb = "runas" // 以管理员权限运行
                    }
                };
                
                process.Start();
                string output = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
                
                return process.ExitCode == 0;
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"设置网络适配器索引 {interfaceIndex} 的DNS服务器失败");
                return false;
            }
        }

        /// <summary>
        /// 设置网络适配器为自动获取DNS
        /// </summary>
        /// <param name="interfaceIndex">网络适配器索引</param>
        /// <returns>是否设置成功</returns>
        private static bool SetDnsToAutomatic(int interfaceIndex)
        {
            try
            {
                Process process = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = "netsh.exe",
                        Arguments = $"interface ipv4 set dns name=\"{interfaceIndex}\" source=dhcp",
                        UseShellExecute = false,
                        RedirectStandardOutput = true,
                        CreateNoWindow = true,
                        Verb = "runas" // 以管理员权限运行
                    }
                };
                
                process.Start();
                string output = process.StandardOutput.ReadToEnd();
                process.WaitForExit();
                
                return process.ExitCode == 0;
            }
            catch (Exception ex)
            {
                _logger.Error(ex, $"设置网络适配器索引 {interfaceIndex} 为自动获取DNS失败");
                return false;
            }
        }

        /// <summary>
        /// 网络适配器信息类
        /// </summary>
        private class AdapterInfo
        {
            public int InterfaceIndex { get; set; }
            public required string Name { get; set; }
        }
    }
}